/*
 * @Author: Bernard liangyongkang@lspace.vip
 * @Date: 2024-04-09 20:22:18
 * @LastEditors: Bernard liangyongkang@lspace.vip
 * @LastEditTime: 2024-04-09 20:22:18
 * @FilePath: \graduation-design\server\app\middleware\jwt.go
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
package middleware

import (
	"fmt"
	"server/app/common/response"
	"server/app/services"
	"server/global"
	"strconv"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

func JWTAuth(GuardName string) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		tokenStr := ctx.Request.Header.Get("Authorization")
		if tokenStr == "" {
			response.TokenFail(ctx)
			ctx.Abort()
			return
		}
		//Token 解析校验
		token, err := jwt.ParseWithClaims(tokenStr, &services.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
			return []byte(global.App.Config.Jwt.Secret), nil
		})
		if err != nil || services.JwtService.IsInBlacklist(tokenStr) { //黑名单校验
			fmt.Println(err)
			response.TokenFail(ctx)
			ctx.Abort()
			return
		}
		claims := token.Claims.(*services.CustomClaims)
		//Token 发布者校验
		if claims.Issuer != GuardName {
			response.TokenFail(ctx)
			ctx.Abort()
			return
		}

		//token 续签
		if claims.ExpiresAt-time.Now().Unix() < global.App.Config.Jwt.RefreshGracePeriod {
			lock := global.Lock("refresh_token_lock", global.App.Config.Jwt.JwtBlacklistGracePeriod)
			if lock.Get() {
				err, user := services.JwtService.GetUserInfo(GuardName, claims.Id)
				if err != nil {
					global.App.Log.Error(err.Error())
					lock.Release() //释放
				} else {
					tokenData, _, _ := services.JwtService.CreateToken(GuardName, user)
					ctx.Header("new-token", tokenData.AccessToken)
					ctx.Header("new-expires-in", strconv.Itoa(tokenData.ExpiresIn))
					_ = services.JwtService.JoinBlackList(token)
				}
			}
		}

		ctx.Set("token", token)
		ctx.Set("id", claims.Id)
	}
}
